package com.xls.commonlibrary.ad.adn.reward.util;

import android.annotation.SuppressLint;
import android.text.TextUtils;
import android.webkit.ValueCallback;

import com.google.gson.Gson;
import com.hjq.toast.Toaster;
import com.orhanobut.logger.Logger;
import com.xls.commonlibrary.BuildConfig;
import com.xls.commonlibrary.ad.adn.baidu.BdAdUtil;
import com.xls.commonlibrary.ad.adn.gm.GMRewardUtil;
import com.xls.commonlibrary.ad.adn.reward.bean.AdBean;
import com.xls.commonlibrary.bean.BusinessResult;
import com.xls.commonlibrary.http.Api;
import com.xls.commonlibrary.http.Result;
import com.xls.commonlibrary.http.RetrofitHelper;
import com.xls.commonlibrary.http.biz.CodeRewardUtil;
//import com.xls.commonlibrary.risk.RiskUtil;
import com.xls.commonlibrary.util.AESUtil;
import com.xls.commonlibrary.util.AdSetCacheUtil;
import com.xls.commonlibrary.util.MD5Util;
import com.xls.commonlibrary.util.RSAEncrypt;
import com.xls.commonlibrary.util.SysDataUtil;
import com.xls.commonlibrary.util.encrypt.EncryptUtil;
import com.xls.commonlibrary.util.eventbus.MessageEvent;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;

import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;

import static com.xls.commonlibrary.constant.Const.HYLC_XXL_JL_TEST;
import static com.xls.commonlibrary.constant.Const.HYLC_XXL_JL_TEST_INDEX;
import static com.xls.commonlibrary.util.eventbus.ConstEventBus.EVENT_AD_GET_POINT;

public class ShowRewardAdsUtil {// 激励视频，播放工具

    // 按顺序播放4家广告，成功一个结束，新的ecpm传给服务器
    private static volatile ShowRewardAdsUtil singleton = null;

    private ShowRewardAdsUtil() {
    }

    public static ShowRewardAdsUtil getInstance() {
        if (singleton == null) {
            synchronized (ShowRewardAdsUtil.class) {
                if (singleton == null) {
                    singleton = new ShowRewardAdsUtil();
                }
            }
        }
        return singleton;
    }

    // 广告看完了的hook
    ValueCallback<String> mCallback = null;
    AdBean mAdBean;

    public void showAd(
            @Nonnull AppCompatActivity activity,
            @NonNull ValueCallback<String> adCallback
    ) {
        // 回调：hook方式
        this.mCallback = adCallback;
        showAd(activity);
    }

    // 播放4家广告，  Gromore必须展示完了广告才能获取其ecpm
    @SuppressLint("CheckResult")
    private void showAd(@Nonnull AppCompatActivity activity) {
        // 回调：eventbus通知的方式

        // 4 ads
        Observable<AdBean> o1 = Observable.create(emitter -> {

//            GromoreUtilOLDNotUseAnyMore.getInstance(activity).showAd(bean -> {
//                Logger.d("============showAd====gm========" + bean.toString());
//                emitter.onNext(bean);
//                emitter.onComplete();
//            });

            GMRewardUtil.getInstance().loadReward(activity, bean -> {
                Logger.d("============showAd====gm========" + bean.toString());
                emitter.onNext(bean);

                emitter.onComplete();
            });

        });

        Observable<AdBean> o2 = Observable.create(emitter -> {

//            TxRewardUtil.getInstance(activity).showAd(bean -> {
//                Logger.d("============showAd====tx========" + bean.toString());
//                emitter.onNext(bean);
//
//                emitter.onComplete();// 返回一次就complete
//            });

        });

        Observable<AdBean> o3 = Observable.create(emitter -> {

//            KsAdUtil.getInstance(activity).showAd(bean -> {
//                Logger.d("============showAd====ks========" + bean.toString());
//                emitter.onNext(bean);
//
//                emitter.onComplete();
//            });

        });

        Observable<AdBean> o4 = Observable.create(emitter -> {

            BdAdUtil.getInstance(activity).showAd(bean -> {
                Logger.d("============showAd====bd========" + bean.toString());
                emitter.onNext(bean);

                emitter.onComplete();
            });

        });

        // 都失败的默认bean
        // 默认空包
        AdBean defaultBean = new AdBean();
        defaultBean.setShowSuccess(false);


        // sorts the ad obs by server info
        List<Observable<AdBean>> list = new ArrayList<>();

        // 按照  服务器 顺序 add即可
        // Set<String> playSet = AdSetCacheUtil.getInstance().getPlayList();
        List<String> playList = AdSetCacheUtil.getInstance().getPlayList();
        for (String ad : playList) {
            if ("csj".equals(ad)) {
                list.add(o1);
            } else if ("tx".equals(ad)) {
                list.add(o2);
            } else if ("ks".equals(ad)) {
                list.add(o3);
            } else if ("bd".equals(ad)) {
                list.add(o4);
            }
        }

        // fixme 转换有问题？
        // .concatArray(arr)
        Observable<AdBean>[] arr = list.toArray(new Observable[list.size()]);

        Logger.d("=======showAd==========size:" + list.size());

        // todo stream onError 放到最后处理，不妨碍下个广告的请求
        // 操作符：onErrorReturn
        Observable
//                .concatDelayError(list)// 错误滞后处理，不打断后续流  todo 需要重新拉广告才这么用
                .concatArray(arr)// emitter.onComplete();才能继续流传
                // .onErrorReturnItem(defaultBean)// 失败，就发个默认空包,不要妨碍后续ad的尝试

                .takeUntil(bean -> {

                    Logger.d("=======showAd=======takeUntil===");
                    Logger.d(bean.toString());

                    return bean.isShowSuccess();
                })
                // 取成功的
                .last(defaultBean)//默认空包
                .subscribeOn(AndroidSchedulers.mainThread())
                // 调接口
                .flatMapObservable((Function<AdBean, ObservableSource<Result<BusinessResult>>>) bean -> {


                    Logger.d("=======showAd====flatMapObservable======AdBean:");
                    Logger.d(bean.toString());

                    // todo flatmap 空ob怎么处理？
//                    if (bean.isShowSuccess()) {
//                        // 有成功的，请求接口
//                    } else {
//                        // 都失败了,不上传了
//                    }

                    // 拼接参数，调服务器接口
                    Map<String, String> p = new HashMap<>();
                    p.put("appName", SysDataUtil.getInstance().getPkName());
                    p.put("company", bean.getAdn());
//                    p.put("ecmp", bean.getEcpm());// 有-1的情况
                    p.put("xls", EncryptUtil.aesEncrypt(bean.getEcpm()));// 加密 改名传ecpm
                    p.put("flag", "2");
                    p.put("adType", "1");

                    // 上传
                    return RetrofitHelper.getInstance().create(Api.class).business(p);

                })
                .subscribeOn(Schedulers.io())

                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        result -> {
                            if (result.getCode() == 1) {
                                // update 2 sets
                                AdSetCacheUtil.getInstance().saveEditList(result.getData().getEditList());
                                AdSetCacheUtil.getInstance().savePlayList(result.getData().getPlayList());

                                // 成功，获取积分信息
                                // 两种回调选一种即可
                                if (this.mCallback != null) {
                                    Logger.d("=======showAd==4==mCallback==方式===");

                                    this.mCallback.onReceiveValue("ad showed finish");
                                } else {
                                    Logger.d("=======showAd==4==EventBus==方式===");

                                    EventBus.getDefault().post(new MessageEvent(EVENT_AD_GET_POINT, "get new points"));
                                }


                            } else {
                                // 失败
                                Toaster.show(result.getMsg());

                            }
                        },

                        throwable -> {
                            Logger.d("=======showAd====throwable=====");
                            Logger.d(throwable);
                        });
    }


    // 三个操作符结合 处理 复杂业务
    // todo concatArray + takeUntil + last  处理按顺序播放广告直到第一个成功，的问题
//    public void showAdBySort() {
    // BD project's LastActivity there
    // 4个广告【播放成功】才调用onNext()
//    }


    // Sigmob聚合广告
//    @SuppressLint("CheckResult")
//    public void showAdSigmob(@Nonnull AppCompatActivity activity,
//                             @NonNull ValueCallback<String> adCallback
//    ) {
//        this.mCallback = adCallback;
//
//
//        Observable<AdBean> o5 = Observable.create(emitter -> {
//
//            SigmobRewardUtil.getInstance().showAd(activity, bean -> {
//                Logger.d("============showAd====sigmob========" + bean.toString());
//                emitter.onNext(bean);
//
//                emitter.onComplete();
//            });
//
//        });
//
//        // 都失败的默认bean
//        // 默认空包
//        AdBean defaultBean = new AdBean();
//        defaultBean.setShowSuccess(false);
//
//        o5.subscribeOn(AndroidSchedulers.mainThread())
//                // 调接口
//                .flatMap((Function<AdBean, ObservableSource<Result<BusinessResult>>>) bean -> {
//
//
//                    Logger.d("=======showSigmobAd====flatMapObservable======AdBean:");
//                    Logger.d(bean.toString());
//
//                    // 拼接参数，调服务器接口
//                    Map<String, String> p = new HashMap<>();
//                    p.put("appName", SysDataUtil.getInstance().getPkName());
//                    p.put("company", bean.getAdn());
//                    if (bean.isShowSuccess()) {
//                        p.put("xls", EncryptUtil.aesEncrypt(bean.getEcpm()));// 加密 改名传ecpm
//                    } else {
//                        p.put("xls", "-1");// 有-1的情况 广告拉取失败了
//                    }
//                    p.put("flag", "2");
//                    p.put("adType", "1");
//
//                    // 上传
//                    return RetrofitHelper.getInstance().create(Api.class).business(p);
//
//                })
//                .subscribeOn(Schedulers.io())
//
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(
//                        result -> {
//                            if (result.getCode() == 1) {
//                                // 成功，获取积分信息
//                                // 两种回调选一种即可
//                                if (this.mCallback != null) {
//                                    Logger.d("=======showAd==4==mCallback==方式===");
//                                    this.mCallback.onReceiveValue("ad showed finish");
//                                }
//                            } else {
//                                // 失败
//                                Toaster.show(result.getMsg());
//                            }
//                        },
//
//                        throwable -> {
//                            Logger.d("=======showAd====throwable=====");
//                            Logger.d(throwable);
//                            Toaster.show(throwable.toString());
//                        });
//    }


    // Gromore激励视频广告
    @SuppressLint("CheckResult")
    public void showAdGM(@Nonnull AppCompatActivity activity,
                         @NonNull ValueCallback<String> adCallback
    ) {


//        RiskUtil.getInstance().reportRisk("activity");


        String adid = CodeRewardUtil.getInstance().getAdId(HYLC_XXL_JL_TEST, HYLC_XXL_JL_TEST_INDEX);


        this.mCallback = adCallback;


        Observable<AdBean> o5 = Observable.create(emitter -> {

            GMRewardUtil.getInstance().loadReward(
//                     "102599093", // test adid
                    adid,
                    activity,
                    bean -> {
                        this.mAdBean = bean;

                        Logger.d("============showAd====sigmob========" + bean.toString());
                        emitter.onNext(bean);

                        emitter.onComplete();
                    });

        });

        // 都失败的默认bean
        // 默认空包
        AdBean defaultBean = new AdBean();
        defaultBean.setShowSuccess(false);

        o5.subscribeOn(AndroidSchedulers.mainThread())
                // 调接口
                .flatMap((Function<AdBean, ObservableSource<Result<BusinessResult>>>) bean -> {


                    Logger.d("=======showAdGM====flatMapObservable======AdBean:");
                    Logger.d(bean.toString());

                    // 拼接参数，调服务器接口
                    LinkedHashMap<String, String> p = new LinkedHashMap<>();
                    p.put("appName", SysDataUtil.getInstance().getPkName());
                    p.put("company", bean.getAdn());
                    p.put("requestId", bean.getRequestId());
                    p.put("isRewardValid", bean.isRewardValid() ? "1" : "0");
                    if (bean.isShowSuccess()) {
                        p.put("xls", bean.getEcpm());// 加密 改名传ecpm
                    } else {
                        p.put("xls", "-1");// 有-1的情况 广告拉取失败了
                    }
                    p.put("flag", "2");
                    p.put("adType", "1");
                    p.put("time", System.currentTimeMillis()+"");
                    p.put("random", AESUtil.getGUID());
                    Gson gson=new Gson();
                    String sign = MD5Util.encodeByMD5(gson.toJson(p));
                    p.put("sign", sign);
                    p.put("transId", bean.getReward());
                    String Extra= AESUtil.encryptCBC_B(gson.toJson(p));
                    String data= RSAEncrypt.encrypt(Extra,RSAEncrypt.publicKey);
                    String data2=RSAEncrypt.getEncByte(data);
                    Map<String, String> json = new HashMap<>();
                    json.put("macData",data2);
                    json.put("newType","1");
                    // 上传
                    return RetrofitHelper.getInstance().create(Api.class).business(json);

                })
                .subscribeOn(Schedulers.io())

                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        result -> {
                            if (result.getCode() == 1) {
                                // 成功，获取积分信息
                                // 两种回调选一种即可
                                if (this.mCallback != null && this.mAdBean != null) {
                                    Logger.d("=======showAd==4==mCallback==方式===");
                                    if (TextUtils.isEmpty(this.mAdBean.getTransId())) {
                                        // todo 正式-不显示
                                        if (BuildConfig.DEBUG) {
                                            Toaster.show("TransId 为空");
                                        }
                                    } else {
                                        this.mCallback.onReceiveValue(this.mAdBean.getTransId());
                                    }
                                }
                            } else if (result.getCode() == -2) {
                                // "参数无效" 不显示了
                                // 广告没有ecpm的情况

                            } else {
                                // 失败
                                Toaster.show(result.getMsg());
                            }
                            this.mAdBean = null;
                        },

                        throwable -> {
                            this.mAdBean = null;
                            Logger.d("=======showAd====throwable=====");
                            Logger.d(throwable);
                            Toaster.show(throwable.toString());
                        });
    }
}
